﻿/*************************************************************************************
 * 文 件 名:   IHK_LoginRegisterSystem
 * 
 * 描    述:   Unity客户端 与 NodeJsServer服务器端通信功能模块
 *            1.NodeJs 服务器端测试代码在工程根目录下(NodeJs_Server文件夹)
 *            2.NodeJs 服务器端数据存储目前使用的Json，可拓展为MySQL等数据库
 *            3.服务器地址和路由配置文件在StreamingAssets文件夹下
 *            4.Unity客户端分为普通用户和管理员两种类型
 *            5.目前已有功能如下：用户登录、新用户注册、请求用户列表、管理用户列表（删除用户）
 * 
 * 版    本：  V1.0
 * 创 建 者：  京产肠饭
 * 创建时间：  2022/5/14
 * 链   接：  https://gitee.com/JingChanChangFan/hk_-unity-tools
*************************************************************************************/

using System;
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;
using QFramework;

/// <summary>
/// 用户登陆时，输入信息的结构
/// </summary>
public class LoginInfo
{
    public LoginInfo(string username, string password, string accountType)
    {
        this.Username = username;
        this.Password = password;
        this.AccountType = accountType;
    }

    public string Username { get; private set; }
    public string Password { get; private set; }
    public string AccountType { get; private set; }
}

/// <summary>
/// 用户注册时，输入信息的结构
/// </summary>
public class RegisterInfo
{
    public RegisterInfo(string username, string password, string realName)
    {
        this.Username = username;
        this.Password = password;
        this.RealName = realName;
    }

    public string Username { get; private set; }
    public string Password { get; private set; }
    public string RealName { get; private set; }
}

public interface IHK_LoginRegisterSystem : ISystem
{
    /// <summary>
    /// 与 NodeJsServer 服务器通信，请求用户登录的接口（供管理端、用户端使用）
    /// </summary>
    /// <param name="loginInfo">用户登陆时的输入信息</param>
    /// <param name="callback">登陆是否成功的回调函数</param>
    void PostLoginMsg(LoginInfo loginInfo, Action<bool> callback);

    /// <summary>
    /// 与 NodeJsServer 服务器通信，请求用户注册的接口（供用户端使用）
    /// </summary>
    /// <param name="registerInfo">用户注册时的输入信息</param>
    /// <param name="callback">注册是否成功的回调函数</param>
    void PostRegisterMsg(RegisterInfo registerInfo, Action<bool> callback);

    /// <summary>
    /// 与 NodeJsServer 服务器通信，请求用户列表的接口（供管理端使用）
    /// </summary>
    /// <param name="callback">获取用户列表的回调</param>
    void GetUserList(Action<string> callback);

    /// <summary>
    /// 与 NodeJsServer 服务器通信，请求删除指定用户（供管理端使用）
    /// </summary>
    /// <param name="username">指定的用户名</param>
    void PostDeleAppointUser(string username);
}

[Serializable]
public class ServerConfig
{
    // 服务器的URL
    public string serverURL;
    // 请求登录的路由URL
    public string loginRouter;
    // 请求注册的路由URL
    public string registerRouter;
    // 请求用户列表的路由URL
    public string userListRouter;
    // 删除指定用户的路由URL
    public string deleAppointUserRouter;
}

public class HK_LoginRegisterSystem : AbstractSystem, IHK_LoginRegisterSystem
{
    // 服务器端配置文件
    ServerConfig config;

    // 登陆注册使用的MonoBehavirour工具脚本
    LoginRegister loginRegister;

    protected override void OnInit()
    {
        // 该模块初始化时，实例化一个LoginRegister工具脚本对象
        if (loginRegister == null)
            loginRegister = new GameObject().AddComponent<LoginRegister>();

        // 从 StreamingAssets 路径下获取服务器URL配置文件，读取到 serverURL
        string configPath = Application.streamingAssetsPath + "/HK_LoginRegisterConfig.txt";

        using (UnityWebRequest requrest = UnityWebRequest.Get(configPath))
        {
            var operation = requrest.SendWebRequest();
            while (!operation.isDone) { }
            if (requrest.error != null)
                Debug.Log(requrest.error);

            string configStr = requrest.downloadHandler.text;

            config = JsonUtility.FromJson<ServerConfig>(configStr);

            Debug.Log("服务器地址URL：" + config.serverURL);
        }
    }

    /// <summary>
    /// 向服务器端发送登录信息
    /// </summary>
    public void PostLoginMsg(LoginInfo loginInfo, Action<bool> callback)
    {
        string url = config.serverURL + config.loginRouter;

        WWWForm form = new WWWForm();
        form.AddField("username", loginInfo.Username);
        form.AddField("password", loginInfo.Password);
        form.AddField("accountType", loginInfo.AccountType);

        loginRegister.PostLoginMsg(url, form, callback);
    }

    /// <summary>
    /// 向服务器发送注册信息
    /// </summary>
    public void PostRegisterMsg(RegisterInfo registerInfo, Action<bool> callback)
    {
        string url = config.serverURL + config.registerRouter;

        WWWForm form = new WWWForm();
        form.AddField("username", registerInfo.Username);
        form.AddField("password", registerInfo.Password);
        form.AddField("realName", registerInfo.RealName);

        loginRegister.PostRegisterMsg(url, form, callback);
    }

    /// <summary>
    /// 与 NodeJsServer 服务器通信，请求用户列表的接口（供管理端使用）
    /// </summary>
    public void GetUserList(Action<string> callback)
    {
        string url = config.serverURL + config.userListRouter;

        loginRegister.GetUserList(url, callback);
    }

    /// <summary>
    /// 与 NodeJsServer 服务器通信，请求删除指定用户（供管理端使用）
    /// </summary>
    public void PostDeleAppointUser(string username)
    {
        string url = config.serverURL + config.deleAppointUserRouter;

        WWWForm form = new WWWForm();
        form.AddField("username", username);

        loginRegister.PostDeleAppointUser(url, form);
    }
}

/// <summary>
/// 登陆注册使用的MonoBehavirour工具脚本
/// </summary>
public class LoginRegister : MonoBehaviour
{
    public void PostLoginMsg(string url, WWWForm form, Action<bool> callback)
    {
        StartCoroutine(LoginAndRegister_IE(url, form, callback));
    }

    public void PostRegisterMsg(string url, WWWForm form, Action<bool> callback)
    {
        StartCoroutine(LoginAndRegister_IE(url, form, callback));
    }

    public void GetUserList(string url, Action<string> callback)
    {
        StartCoroutine(GetUserList_IE(url, callback));
    }

    public void PostDeleAppointUser(string url, WWWForm form)
    {
        StartCoroutine(PostDeleAppointUser_IE(url, form));
    }

    // 登陆注册的 Post 请求
    IEnumerator LoginAndRegister_IE(string url, WWWForm form, Action<bool> callback)
    {
        using (UnityWebRequest request = UnityWebRequest.Post(url, form))
        {
            yield return request.SendWebRequest();

            if (!string.IsNullOrEmpty(request.error))
                Debug.LogError(request.error);

            if (request.downloadHandler.text == "true")
                callback(true);
            else
                callback(false);
        }
    }

    // 获取用户列表的 Get 请求
    IEnumerator GetUserList_IE(string url, Action<string> callback)
    {
        using (UnityWebRequest request = UnityWebRequest.Get(url))
        {
            yield return request.SendWebRequest();

            if (!string.IsNullOrEmpty(request.error))
                Debug.LogError(request.error);

            callback(request.downloadHandler.text);
        }
    }

    // 删除指定用户 Post 请求
    IEnumerator PostDeleAppointUser_IE(string url, WWWForm form)
    {
        using (UnityWebRequest request = UnityWebRequest.Post(url, form))
        {
            yield return request.SendWebRequest();

            if (!string.IsNullOrEmpty(request.error))
                Debug.LogError(request.error);
        }
    }
}